package com.cn.web.service.impl;



import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cn.api.ApiResult;
import com.cn.mapper.SysPermissionMapper;
import com.cn.mapper.SysUserMapper;
import com.cn.mapper.SysUserPermissionRelationMapper;
import com.cn.param.LoginUserParam;
import com.cn.pojo.SysPermission;
import com.cn.pojo.SysUser;
import com.cn.pojo.SysUserPermissionRelation;
import com.cn.security.entity.LogUser;
import com.cn.utils.JwtUtils;
import com.cn.utils.RedisUtil;
import com.cn.web.service.LogService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;
import java.util.Objects;

@Service
public class LogServiceImpl implements LogService {

    @Autowired
    private RedisUtil redisUtil;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    private SysUserMapper sysUserMapper;

    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;

    @Autowired
    private SysPermissionMapper sysPermissionMapper;

    @Autowired
    private SysUserPermissionRelationMapper sysUserPermissionRelationMapper;

    @Override
    public ApiResult login(LoginUserParam param) {

        // 1 获取AuthenticationManager 对象 然后调用 authenticate() 方法
        // UsernamePasswordAuthenticationToken 实现了Authentication 接口
        UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(param.getUserName(), param.getPassword());
        Authentication authenticate = authenticationManager.authenticate(authenticationToken);

        //2 认证没通过 提示认证失败
        if (Objects.isNull(authenticate)) {
            throw new RuntimeException("认证失败用户信息不存在");
        }

        //认证通过 使用userid 生成jwt token令牌
        LogUser loginUser = (LogUser) authenticate.getDetails();
        String userId = loginUser.getUser().getUserId().toString();

        Map<String, String> payloadMap = new HashMap<>();
        payloadMap.put("userId", userId);
        payloadMap.put("userName", loginUser.getUser().getUserName());
        payloadMap.put("token", JwtUtils.generateToken(payloadMap));

        boolean resultRedis = redisUtil.set("login:" + userId, loginUser);

        if(!resultRedis){
            throw new RuntimeException("redis连接不上，登录失败");
        }
        return ApiResult.success(payloadMap);
    }

    @Override
    public ApiResult logOut() {
        // 1 获取 SecurityContextHolder 中的用户id
        UsernamePasswordAuthenticationToken authentication = (UsernamePasswordAuthenticationToken) SecurityContextHolder.getContext().getAuthentication();
        LogUser loginUser = (LogUser)authentication.getPrincipal();
        //2 删除redis 中的缓存信
        String key = "login:"+loginUser.getUser().getUserId().toString();
        redisUtil.del(key);
        return ApiResult.success("退出成功!");

    }

    /**
     * 用户注册
     * @param param
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public ApiResult register(LoginUserParam param) {
        LambdaQueryWrapper<SysUser> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysUser::getAccount,param.getUserName());
        SysUser user = sysUserMapper.selectOne(queryWrapper);
        if (user != null) {
            throw new RuntimeException("用户名称重复");
        }
        SysUser sysUser = new SysUser();
        sysUser.setAccount(param.getUserName());
        //密码加密
        String encode = bCryptPasswordEncoder.encode(param.getPassword());
        sysUser.setPassword(encode);
        //保存用户
        sysUserMapper.insert(sysUser);
        //保存权限
        SysPermission sysPermission = new SysPermission();
        sysPermission.setPermissionCode("sys:queryUser");
        sysPermission.setPermissionName("查询用户");
        sysPermission.setUrl("/getUser");
        sysPermissionMapper.insert(sysPermission);
        //保存关系
        SysUserPermissionRelation sysUserPermissionRelation = new SysUserPermissionRelation();
        sysUserPermissionRelation.setPermissionId(sysPermission.getPermissionId());
        sysUserPermissionRelation.setUserId(sysUser.getUserId());
        sysUserPermissionRelationMapper.insert(sysUserPermissionRelation);
        return ApiResult.success("保存成功");
    }

}

